import React from 'react';
import ReactDOM from 'react-dom';
import { connect, Provider } from 'react-redux';
import { createStore, combineReducers, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import * as sagaEffects from 'redux-saga/effects';
export { connect };

function dva(){
    const app = {
        _models:[],
        model,
        _router:null,
        router,
        start,
        createAction,
    }
    const initialReducers = {};
    function model(modelConfig){
        const prefixedModel = prefixNamespace(modelConfig);
        app._models.push(prefixedModel)
    }
    function router(routerConfig){
        app._router = routerConfig
    }
    function createAction(){
        let actionCreators = {};
        for (const model of app._models) {
            let { reducers } = model;
            for (let key in reducers) {
                // counter/add =>  action {type:'counter/add'}
                actionCreators[key] = () => ({ type: key })
            }
        }
        console.log(actionCreators)
        return actionCreators
    }    
    function start(root){
        for (const model of app._models) {
            initialReducers[model.namespace] = getReducer(model)
        }
        let rootReducer = combineReducers(initialReducers)
        // 从app中回去saga的数组
        const sagas = getSagas(app)
        const sagaMiddleware = createSagaMiddleware();
        let store = applyMiddleware(sagaMiddleware)(createStore)(rootReducer)
        // 全部启动
        sagas.forEach(saga=>sagaMiddleware.run(saga))
        ReactDOM.render(
            <Provider store = {store}>
                {app._router()}
            </Provider>,document.querySelector(root))
    }
    function getSagas(app){
        let sagas = []
        for (const model of app._models) {
            let saga = getSaga(model)
            sagas.push(saga)
        }
        return sagas
    }
    return app
}
export default dva

function getSaga(model){
    let { effects } = model
    return function* (){
        for (const key in effects) {  //key=counter/asyncAdd
            const watcherSaga = getWatcher(key,effects[key],model)
            yield sagaEffects.fork(watcherSaga)
        }
    }
}

function getWatcher(key,effect,model){
    return function* watcherSaga(){
        //key=asyncAdd
        // yield sagaEffects.takeEvery(key,effect)
        yield sagaEffects.takeEvery(key,function* (action){
            yield effect(action,{
                ...sagaEffects,put:action=>sagaEffects.put(
                    {...action,type: prefixType(action.type, model)}
                )
            })
        })

    }
}
function prefixType(type,model){
    console.log(type)
    if(type.indexOf('/')===-1){
        return `${model.namespace}/${type}`
    }
    return type
}

// 把model里的reducer 对象转成reducer函数
function getReducer(model){
    let { reducers, state: defaultState } = model;
    let reducer = (state = defaultState,action)=>{
        let reducer = reducers[action.type]
        if(reducer){
            return reducer(state,action)
        }else{
            return state
        }
    }   
    return reducer
}
/**
 * 将reducers中加入命名空间名字
 * @param {*} model 定义的模型
 */
function prefixNamespace(model){
    if(model.reducers){
        model.reducers = prefix(model.reducers, model.namespace);
    }
    if(model.effects){
        model.effects = prefix(model.effects, model.namespace);
    }
    return model
}
function prefix(obj, namespace){
    let newObj = {} 
    for (const key in obj) {
        newObj[namespace+'/'+key] = obj[key]
    }
    return newObj
}
